package com.itheima.stock.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itheima.stock.constant.StockConstant;
import com.itheima.stock.mapper.SysPermissionMapper;
import com.itheima.stock.pojo.entity.SysPermission;
import com.itheima.stock.pojo.entity.SysUser;
import com.itheima.stock.mapper.SysUserMapper;
import com.itheima.stock.pojo.vo.MenusAndChildrenVo;
import com.itheima.stock.service.ISysUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.vo.res.LoginReqVo;
import com.itheima.stock.vo.resp.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author 哈纳桑
 * @since 2024-06-03
 */
@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Resource
    private AuthenticationManager authenticationManager;
    @Resource
    private IdWorker idWorker;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private SysPermissionMapper permissionMapper;
    @Override
    public R<LoginRespVo> login(LoginReqVo loginReqVo) {
        //1.参数合法性判断
        if (loginReqVo==null||
            !StringUtils.hasText(loginReqVo.getUsername())||
            !StringUtils.hasText(loginReqVo.getPassword())||
            !StringUtils.hasText(loginReqVo.getCode())){
            return R.error(ResponseCode.DATA_ERROR);
        }
        //1.1校验验证码
        String sessionId = loginReqVo.getSessionId();
        String code = (String) redisTemplate.opsForValue().get("CK:" + sessionId);

        if (!code.equals(loginReqVo.getCode())){
            return R.error(ResponseCode.CHECK_CODE_ERROR);
        }
        //2.数据封装
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginReqVo.getUsername(), loginReqVo.getPassword());

        //3.调用认证管理器进行认证
        Authentication authenticated = authenticationManager.authenticate(authenticationToken);

        //4.获取认证结果
        LoginUser loginUser = (LoginUser) authenticated.getPrincipal();

        //5.获取权限菜单树
        //5.1获取所有顶级目录
        List<MenusAndChildrenVo> superMenuList = permissionMapper.getMenuList(null, 1 );

        //5.2构建树
        List<MenusAndChildrenVo> menuTree = buildMenuTree(superMenuList);

        //6.数据封装
        LoginRespVo loginRespVo = new LoginRespVo();
        BeanUtils.copyProperties(loginUser.getUser(),loginRespVo);
        loginRespVo.setPermissions(loginUser.getPermissions());
        loginRespVo.setMenus(menuTree);

        //7.返回
        return R.ok(loginRespVo);
    }

    @Override
    public R<Map<String, String>> getCaptchaCode() {
        //1.使用htool生成验证码
        /**
         * 参数1：宽度
         * 参数2：高度
         * 参数3：验证码长度
         * 参数4：验证码干扰线
         */
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(250, 40, 4, 20);

        //1.2设置背景颜色
        lineCaptcha.setBackground(Color.LIGHT_GRAY);

        //1.3获取校验码
        String code = lineCaptcha.getCode();

        //1.4获取经过base64编码的验证码图片
        String imageBase64 = lineCaptcha.getImageBase64();

        //2.生成Sessionid 转换为 String 避免前端精度丢失
        String sessionId = String.valueOf(idWorker.nextId());

        log.info("会话ID:{},校验码:{}",sessionId,code);

        //2.1将验证码和sessionid保存到redis中
        redisTemplate.opsForValue().set(StockConstant.CHECK_PREFIX +sessionId,code,5, TimeUnit.MINUTES);

        //3.封装数据
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("imageData",imageBase64);
        hashMap.put("sessionId",sessionId);

        return R.ok(hashMap);
    }

    private List<MenusAndChildrenVo> buildMenuTree(List<MenusAndChildrenVo>  parentTree){
        //查询对应子菜单
        for (MenusAndChildrenVo menusAndChildrenVo : parentTree) {
            List<MenusAndChildrenVo> childrenVOs = permissionMapper.getMenuList(menusAndChildrenVo.getId(),2);
            //子菜单下的孩子
            List<MenusAndChildrenVo> menusAndChildrenVos1 = buildMenuTree(childrenVOs);
            menusAndChildrenVo.setChildren(menusAndChildrenVos1);
        }
        return parentTree;

    }
}
